﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using Jayden.Dll.Cards.Poker.Enums;
using System.Drawing;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
using Jayden.Dll.Cards.Drawing;

namespace Jayden.Dll.Cards.Poker
{
	public abstract class PokerClient
	{
		private int m_Port;
		private string m_Host;
		private PokerSocket m_Socket;
		private bool m_Running = false;
		private string m_Login;
		private ulong m_Bankroll;
		private Dictionary<string, int> m_ActionKeys = new Dictionary<string,int>();
		private bool m_UseSsl = true;

		public PokerClient(string host, int port)
		{
			m_Port = port;
			m_Host = host;
		}

		public string Login { get { return m_Login; } }
		public int GetActionKey(string tableName)
		{
			lock (m_ActionKeys)
			{
				int key = -1;
				if (m_ActionKeys.TryGetValue(tableName, out key))
					return key;
			}
			return -1;
		}

		public void Run()
		{
			try
			{
				m_Running = true;
				Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
				OnClientMessage(string.Format("Trying to connect to server {0} on port {1} ...", m_Host, m_Port));
				socket.Connect(m_Host, m_Port);
				OnClientMessage(string.Format("Connected to server {0} on port {1}.", m_Host, m_Port));
				m_Socket = new PokerSocket(socket);

				m_Socket.WriteUInt64(PokerProtocol.Header);
				m_Socket.WriteString(PokerProtocol.ProtocolName);
				m_Socket.WriteUInt64(PokerProtocol.Version);

				OnClientMessage(string.Format("Handshake sent. Waiting for messages ..."));
				if (m_UseSsl)
				{
					m_Socket.SslStream.AuthenticateAsClient("onlinePoker");
					m_Socket.Encrypted = true;
					OnClientMessage(string.Format("Connection is now secured using ssl ..."));
				}

				OnClientConnected();

				int messageId = 0x00;
				while (m_Running)
				{
					messageId = m_Socket.ReadInt32();
					OnReceivingMessage(messageId);
				}
			}
			catch (Exception e)
			{
				OnException(e);
			}
			OnClientDisconnected();
		}

		public void LogIn(string login, string password)
		{
			lock (m_Socket)
			{
				m_Socket.WriteInt32((int)PokerProtocolMessageType.Login);
				m_Socket.WriteString(login);
				m_Socket.WriteString(password);
			}
		}

		public void AskBankroll()
		{
			lock (m_Socket)
			{
				m_Socket.WriteInt32((int)PokerProtocolMessageType.Bankroll);
			}
		}

		public void LogOut()
		{
			lock (m_Socket)
			{
				m_Socket.WriteInt32((int)PokerProtocolMessageType.Logout);
			}
		}

		public void Observe(string tableName)
		{
			lock (m_Socket)
			{
				m_Socket.WriteInt32((int)PokerProtocolMessageType.Observe);
				m_Socket.WriteString(tableName);
			}
		}

		public void AskBuyIn(string tableName, int seatIndex)
		{
			lock (m_Socket)
			{
				m_Socket.WriteInt32((int)PokerProtocolMessageType.AskBuyIn);
				m_Socket.WriteString(tableName);
				m_Socket.WriteByte((byte)seatIndex);
			}
		}

		public void Sit(string tableName, int seatIndex, ulong amount)
		{
			lock (m_Socket)
			{
				m_Socket.WriteInt32((int)PokerProtocolMessageType.Sit);
				m_Socket.WriteString(tableName);
				m_Socket.WriteByte((byte)seatIndex);
				m_Socket.WriteUInt64(amount);
			}
		}
		public void ReBuy(string tableName, ulong amount)
		{
			lock (m_Socket)
			{
				m_Socket.WriteInt32((int)PokerProtocolMessageType.ReBuy);
				m_Socket.WriteString(tableName);
				m_Socket.WriteUInt64(amount);
			}
		}

		public void Leave(string tableName)
		{
			lock (m_Socket)
			{
				m_Socket.WriteInt32((int)PokerProtocolMessageType.Leave);
				m_Socket.WriteString(tableName);
			}
		}

		public void SitOut(string tableName)
		{
			lock (m_Socket)
			{
				m_Socket.WriteInt32((int)PokerProtocolMessageType.SitOut);
				m_Socket.WriteString(tableName);
			}
		}

		public void Waiting(string tableName)
		{
			lock (m_Socket)
			{
				m_Socket.WriteInt32((int)PokerProtocolMessageType.Waiting);
				m_Socket.WriteString(tableName);
			}
		}

		public void TournamentLobby(string tournamentName)
		{
			lock (m_Socket)
			{
				m_Socket.WriteInt32((int)PokerProtocolMessageType.TournamentLobby);
				m_Socket.WriteString(tournamentName);
			}
		}

		public void TournamentLobbyPlayers(string tournamentName)
		{
			lock (m_Socket)
			{
				m_Socket.WriteInt32((int)PokerProtocolMessageType.TournamentLobbyPlayers);
				m_Socket.WriteString(tournamentName);
			}
		}

		public void TournamentLobbyBettingStructure(string tournamentName)
		{
			lock (m_Socket)
			{
				m_Socket.WriteInt32((int)PokerProtocolMessageType.TournamentLobbyBettingStructure);
				m_Socket.WriteString(tournamentName);
			}
		}

		public void TournamentLobbyPayoutStructure(string tournamentName)
		{
			lock (m_Socket)
			{
				m_Socket.WriteInt32((int)PokerProtocolMessageType.TournamentLobbyPayoutStructure);
				m_Socket.WriteString(tournamentName);
			}
		}

		public void TournamentRebuy(string tournamentName, byte rebuyCount)
		{
			lock (m_Socket)
			{
				m_Socket.WriteInt32((int)PokerProtocolMessageType.TournamentRebuy);
				m_Socket.WriteString(tournamentName);
				m_Socket.WriteInt32(GetActionKey(tournamentName));
				m_Socket.WriteByte(rebuyCount);
			}
		}

		public void TournamentAddOn(string tournamentName, byte addOnCount)
		{
			lock (m_Socket)
			{
				m_Socket.WriteInt32((int)PokerProtocolMessageType.TournamentAddOn);
				m_Socket.WriteString(tournamentName);
				m_Socket.WriteByte(addOnCount);
			}
		}

		public void Register(string tournamentName)
		{
			lock (m_Socket)
			{
				m_Socket.WriteInt32((int)PokerProtocolMessageType.TournamentRegister);
				m_Socket.WriteString(tournamentName);
			}
		}

		public void Unregister(string tournamentName)
		{
			lock (m_Socket)
			{
				m_Socket.WriteInt32((int)PokerProtocolMessageType.TournamentUnregister);
				m_Socket.WriteString(tournamentName);
			}
		}

		public void SendAction(string tableName, ulong amount)
		{
			lock (m_Socket)
			{
				m_Socket.WriteInt32((int)PokerProtocolMessageType.Action);
				m_Socket.WriteString(tableName);
				m_Socket.WriteInt32(GetActionKey(tableName));
				m_Socket.WriteUInt64(amount);
			}
		}

		public void SendActionShow(string tableName, bool show)
		{
			lock (m_Socket)
			{
				m_Socket.WriteInt32((int)PokerProtocolMessageType.ActionShow);
				m_Socket.WriteString(tableName);
				m_Socket.WriteInt32(GetActionKey(tableName));
				m_Socket.WriteBoolean(show);
			}
		}

		public void SendActionPost(string tableName, bool post)
		{
			lock (m_Socket)
			{
				m_Socket.WriteInt32((int)PokerProtocolMessageType.ActionPost);
				m_Socket.WriteString(tableName);
				m_Socket.WriteInt32(GetActionKey(tableName));
				m_Socket.WriteBoolean(post);
			}
		}

		public void SendChatMessage(string tableName, string message)
		{
			if (message == null || string.IsNullOrWhiteSpace(message))
				return;
			lock (m_Socket)
			{
				m_Socket.WriteInt32((int)PokerProtocolMessageType.ChatMessage);
				m_Socket.WriteString(tableName);
				m_Socket.WriteString(message.Trim());
			}
		}

		public void SendTableImage(PlayerImage image)
		{
			lock (m_Socket)
			{
				m_Socket.WriteInt32((int)PokerProtocolMessageType.TableImage);
				m_Socket.WriteImage(image.TableImage);
			}
		}

		public void RequestTableImage(string playerName)
		{
			lock (m_Socket)
			{
				m_Socket.WriteInt32((int)PokerProtocolMessageType.RequestTableImage);
				m_Socket.WriteString(playerName);
			}
		}

		public void ShowCard(string tableName, CardList cards)
		{
			if (cards != null && cards.Count > 0 && cards.Count <= 52)
			{
				lock (m_Socket)
				{
					m_Socket.WriteInt32((int)PokerProtocolMessageType.PlayerShowCards);
					m_Socket.WriteString(tableName);
					m_Socket.WriteCards(cards);
				}
			}
		}

		public void Lobby(PokerLimit limit, PokerType type, ulong minStake, ulong maxStake, ulong minBuyIn, ulong maxBuyIn, string currency, byte minPlayer, byte maxPlayer, byte minSeat, byte maxSeat)
		{
			lock (m_Socket)
			{
				m_Socket.WriteInt32((int)PokerProtocolMessageType.Lobby);
				m_Socket.WriteByte((byte)limit);
				m_Socket.WriteByte((byte)type);
				m_Socket.WriteUInt64(minStake);
				m_Socket.WriteUInt64(maxStake);
				m_Socket.WriteUInt64(minBuyIn);
				m_Socket.WriteUInt64(maxBuyIn);
				m_Socket.WriteString(currency);
				m_Socket.WriteByte(minPlayer);
				m_Socket.WriteByte(maxPlayer);
				m_Socket.WriteByte(minSeat);
				m_Socket.WriteByte(maxSeat);
			}
		}

		protected void OnReceivingMessage(int messageId)
		{
			switch ((PokerProtocolMessageType)messageId)
			{
				case PokerProtocolMessageType.Disconnect:
					m_Running = false;
					break;
				case PokerProtocolMessageType.Message:
					OnServerMessage(m_Socket.ReadString());
					break;
				case PokerProtocolMessageType.Login:
					OnClientLogin();
					break;
				case PokerProtocolMessageType.ClosedCards:
					OnClosedCards();
					break;
				case PokerProtocolMessageType.Action:
					OnAction();
					break;
				case PokerProtocolMessageType.DealerShowCards:
					OnShowCards();
					break;
				case PokerProtocolMessageType.InitTable:
					OnInitTable();
					break;
				case PokerProtocolMessageType.Lobby:
					OnLobby();
					break;
				case PokerProtocolMessageType.ActionShow:
					OnActionShow();
					break;
				case PokerProtocolMessageType.ActionPost:
					OnActionPost();
					break;
				case PokerProtocolMessageType.TableImage:
					OnTableImage();
					break;
				case PokerProtocolMessageType.Timer:
					OnTimer();
					break;
				case PokerProtocolMessageType.ChatMessage:
					OnChatMessage();
					break;
				case PokerProtocolMessageType.Bankroll:
					OnBankroll();
					break;
				case PokerProtocolMessageType.ActionDone:
					OnActionDone();
					break;
				case PokerProtocolMessageType.TournamentFinished:
					OnTournamentFinished();
					break;
				case PokerProtocolMessageType.BlindGoesUp:
					OnBlindGoesUp();
					break;
				case PokerProtocolMessageType.TournamentLobby:
					OnTournamentLobby();
					break;
				case PokerProtocolMessageType.TournamentRegister:
					OnTournamentRegister();
					break;
				case PokerProtocolMessageType.TournamentUnregister:
					OnTournamentUnregister();
					break;
				case PokerProtocolMessageType.TournamentLobbyPlayers:
					OnTournamentLobbyPlayers();
					break;
				case PokerProtocolMessageType.TournamentLobbyBettingStructure:
					OnTournamentLobbyBettingStructure();
					break;
				case PokerProtocolMessageType.TournamentLobbyPayoutStructure:
					OnTournamentLobbyPayoutStructure();
					break;
				case PokerProtocolMessageType.TournamentRebuy:
					OnTournamentRebuy();
					break;
				case PokerProtocolMessageType.KeepAlive:
					OnKeepAlive();
					break;
				case PokerProtocolMessageType.AskBuyIn:
					OnAskBuyIn();
					break;
				default:
					throw new Exception("unknow message #" + messageId + ".");
			}
		}

		protected void OnClientLogin()
		{
			bool connected = m_Socket.ReadBoolean();
			if (connected)
			{
				m_Login = m_Socket.ReadString();
				m_Bankroll = m_Socket.ReadUInt64();
				OnClientLogin(m_Login);
			}
			else
			{
				string login = m_Socket.ReadString();
				string reason = m_Socket.ReadString();
				OnClientLoginFail(login, reason);
			}
		}
		protected void OnClosedCards()
		{
			string tableName = m_Socket.ReadString();
			byte count = m_Socket.ReadByte();
			CardList cards = new CardList();
			for (int c = 0; c < count; c++)
				cards.Add(m_Socket.ReadCard());
			OnClosedCards(tableName, cards);
		}
		protected void OnShowCards()
		{
			string tableName = m_Socket.ReadString();
			byte count = m_Socket.ReadByte();
			CardList cards = new CardList();
			for (int c = 0; c < count; c++)
				cards.Add(m_Socket.ReadCard());
			OnShowCards(tableName, cards);
		}
		protected void OnAction()
		{
			string tableName = m_Socket.ReadString();
			int key = m_Socket.ReadInt32();
			lock (m_ActionKeys)
			{
				m_ActionKeys.Remove(tableName);
				m_ActionKeys.Add(tableName, key);
			}
			int timeOut = m_Socket.ReadInt32();
			ulong call = m_Socket.ReadUInt64();
			ulong raise = m_Socket.ReadUInt64();
			ulong allin = m_Socket.ReadUInt64();
			OnAction(tableName, call, raise, allin, timeOut);
		}
		protected void OnActionShow()
		{
			string tableName = m_Socket.ReadString();
			int key = m_Socket.ReadInt32();
			lock (m_ActionKeys)
			{
				m_ActionKeys.Remove(tableName);
				m_ActionKeys.Add(tableName, key);
			}
			int timeOut = m_Socket.ReadInt32();
			OnActionShow(tableName, timeOut);
		}
		protected void OnActionPost()
		{
			string tableName = m_Socket.ReadString();
			int key = m_Socket.ReadInt32();
			lock (m_ActionKeys)
			{
				m_ActionKeys.Remove(tableName);
				m_ActionKeys.Add(tableName, key);
			}
			int timeOut = m_Socket.ReadInt32();
			bool smallAndBig = m_Socket.ReadBoolean();
			OnActionPost(tableName, smallAndBig, timeOut);
		}
		protected void OnInitTable()
		{
			PokerTableView view = new PokerTableView();
			view.TournamentName = m_Socket.ReadString();
			view.TableName = m_Socket.ReadString();
			view.Currency = m_Socket.ReadString();
			view.Ante = m_Socket.ReadUInt64();
			view.SmallBlind = m_Socket.ReadUInt64();
			view.BigBlind = m_Socket.ReadUInt64();
			view.Button = m_Socket.ReadByte();
			view.Type = (PokerType)m_Socket.ReadByte();
			view.Limit = (PokerLimit)m_Socket.ReadByte();
			view.Street = (PokerStreetType)m_Socket.ReadByte();
			view.CurrentAction = m_Socket.ReadByte();
			byte numberOfCards = m_Socket.ReadByte();
			view.Cards = new Card[numberOfCards];
			for (byte c = 0; c < numberOfCards; c++)
				view.Cards[c] = m_Socket.ReadCard();
			view.Pot = m_Socket.ReadUInt64();
			view.State = (PokerStreetType)m_Socket.ReadByte();
			byte numberOfSeats = m_Socket.ReadByte();
			view.Seats = new PokerTableView.PokerTableSeatView[numberOfSeats];
			byte occupied = m_Socket.ReadByte();
			for (byte c = 0; c < occupied; c++)
			{
				PokerTableView.PokerTableSeatView seat = new PokerTableView.PokerTableSeatView();
				seat.Index = m_Socket.ReadByte();
				seat.Name = m_Socket.ReadString();
				seat.Stack = m_Socket.ReadUInt64();
				seat.State = (PokerSeatState)m_Socket.ReadByte();
				seat.Bet = m_Socket.ReadUInt64();
				byte cardsCount = m_Socket.ReadByte();
				if (cardsCount > 0)
				{
					seat.Cards = new Card[cardsCount];
					for (byte d = 0; d < cardsCount; d++)
					{
						seat.Cards[d] = m_Socket.ReadCard();
					}
				}
				view.Seats[seat.Index] = seat;
			}
			byte leftToTalk = m_Socket.ReadByte();
			view.PlayersLeftToTalk = new byte[leftToTalk];
			for (byte c = 0; c < leftToTalk; c++)
				view.PlayersLeftToTalk[c] = m_Socket.ReadByte();
			OnInitTable(view);
		}
		protected void OnLobby()
		{
			int results = m_Socket.ReadInt32();
			List<PokerTableInfo> cashGames = new List<PokerTableInfo>();
			for (int c = 0; c < results; c++)
			{
				PokerTableInfo info = new PokerTableInfo();
				info.TableName = m_Socket.ReadString();
				info.Limit = (PokerLimit)m_Socket.ReadByte();
				info.Type = (PokerType)m_Socket.ReadByte();
				info.Currency = m_Socket.ReadString();
				info.Ante = m_Socket.ReadUInt64();
				info.SmallBlind = m_Socket.ReadUInt64();
				info.BigBlind = m_Socket.ReadUInt64();
				info.Players = m_Socket.ReadByte();
				info.Seats = m_Socket.ReadByte();
				info.MinimumBuyIn = m_Socket.ReadUInt64();
				info.MaximumBuyIn = m_Socket.ReadUInt64();
				cashGames.Add(info);
			}
			results = m_Socket.ReadInt32();
			List<PokerTournamentInfo> tournaments = new List<PokerTournamentInfo>();
			for (int c = 0; c < results; c++)
			{
				PokerTournamentInfo info = new PokerTournamentInfo();
				info.TournamentName = m_Socket.ReadString();
				info.Limit = (PokerLimit)m_Socket.ReadByte();
				info.Type = (PokerType)m_Socket.ReadByte();
				info.Currency = m_Socket.ReadString();
				info.EntryPrice = m_Socket.ReadUInt64();
				info.EntryRake = m_Socket.ReadUInt64();
				info.MinEntry = m_Socket.ReadInt32();
				info.MaxEntry = m_Socket.ReadInt32();
				info.StartDateTime = m_Socket.ReadDateTime();
				info.Entrants = m_Socket.ReadInt32();
				tournaments.Add(info);
			}
			OnLobby(cashGames, tournaments);
		}
		protected void OnTableImage()
		{
			string playerName = m_Socket.ReadString();
			Image image = m_Socket.ReadImage();
			OnTableImage(playerName, image);
		}
		protected void OnTimer()
		{
			string tableName = m_Socket.ReadString();
			int seatIndex = m_Socket.ReadInt32();
			int timeOut = m_Socket.ReadInt32();
			OnTimer(tableName, seatIndex, timeOut);
		}
		protected void OnChatMessage()
		{
			string tableName = m_Socket.ReadString();
			string playerName = m_Socket.ReadString();
			string message = m_Socket.ReadString();
			OnChatMessage(tableName, playerName, message);
		}
		protected void OnBankroll()
		{
			ulong bankroll = m_Socket.ReadUInt64();
			OnBankroll(bankroll);
		}
		protected void OnActionDone()
		{
			string tableName = m_Socket.ReadString();
			string playerName = m_Socket.ReadString();
			PokerActionType action = (PokerActionType)m_Socket.ReadByte();
			ulong amount = m_Socket.ReadUInt64();
			OnActionDone(tableName, playerName, action, amount);
		}
		protected void OnTournamentFinished()
		{
			string tournamentName = m_Socket.ReadString();
			int position = m_Socket.ReadInt32();
			ulong amount = m_Socket.ReadUInt64();
			PokerCurrency currency = PokerCurrency.GetCurrency(m_Socket.ReadString());
			OnTournamentFinished(tournamentName, position, amount, currency);
		}
		protected void OnBlindGoesUp()
		{
			string tableName= m_Socket.ReadString();
			ulong smallBlind = m_Socket.ReadUInt64();
			ulong bigBlind = m_Socket.ReadUInt64();
			ulong ante = m_Socket.ReadUInt64();
			OnBlindGoesUp(tableName, smallBlind, bigBlind, ante);
		}
		protected void OnTournamentLobby()
		{
			string tournamentName = m_Socket.ReadString();
			bool isRegistred = m_Socket.ReadBoolean();
			int entryCount = m_Socket.ReadInt32();
			ulong entryPrice = m_Socket.ReadUInt64();
			ulong entryRake = m_Socket.ReadUInt64();
			int minEntries = m_Socket.ReadInt32();
			int maxEntries = m_Socket.ReadInt32();
			DateTime startTime = m_Socket.ReadDateTime();
			ulong startingChips = m_Socket.ReadUInt64();
			int playersLeft = m_Socket.ReadInt32();
			OnTournamentLobby(tournamentName, isRegistred);
		}
		protected void OnTournamentRegister()
		{
			string tournamentName = m_Socket.ReadString();
			OnTournamentRegister(tournamentName);
		}
		protected void OnTournamentUnregister()
		{
			string tournamentName = m_Socket.ReadString();
			OnTournamentUnregister(tournamentName);
		}
		protected void OnTournamentLobbyPlayers()
		{
			string tournamentName = m_Socket.ReadString();
			List<KeyValuePair<string, ulong>> players = new List<KeyValuePair<string, ulong>>();
			int count = m_Socket.ReadInt32();
			for (int c = 0; c < count; c++)
			{
				string login = m_Socket.ReadString();
				ulong amount = m_Socket.ReadUInt64();
				players.Add(new KeyValuePair<string, ulong>(login, amount));
			}
			OnTournamentLobbyPlayers(tournamentName, players);
		}

		protected void OnTournamentLobbyBettingStructure()
		{
			string tournamentName = m_Socket.ReadString();
			List<PokerTournamentConfiguration.BettingStructureEntry> bettingStructure = new List<PokerTournamentConfiguration.BettingStructureEntry>();
			int count = m_Socket.ReadInt32();
			for (int c = 0; c < count; c++)
			{
				PokerTournamentConfiguration.BettingStructureEntry entry = new PokerTournamentConfiguration.BettingStructureEntry();
				entry.Level = m_Socket.ReadInt32();
				entry.SmallBlind = m_Socket.ReadUInt64();
				entry.BigBlind = m_Socket.ReadUInt64();
				entry.Ante = m_Socket.ReadUInt64();
				entry.Duration = m_Socket.ReadInt32();
				bettingStructure.Add(entry);
			}
			OnTournamentLobbyBettingStructure(tournamentName, bettingStructure);
		}

		protected void OnTournamentLobbyPayoutStructure()
		{
			string tournamentName = m_Socket.ReadString();
			List<PokerTournamentConfiguration.PayoutEntry> payoutStructure = new List<PokerTournamentConfiguration.PayoutEntry>();
			int count = m_Socket.ReadInt32();
			for (int c = 0; c < count; c++)
			{
				PokerTournamentConfiguration.PayoutEntry entry = new PokerTournamentConfiguration.PayoutEntry();
				entry.FirstPosition = m_Socket.ReadInt32();
				entry.LastPosition = m_Socket.ReadInt32();
				entry.Amount = m_Socket.ReadUInt64();
				payoutStructure.Add(entry);
			}
			OnTournamentLobbyPayoutStructure(tournamentName, payoutStructure);
		}

		protected void OnTournamentRebuy()
		{
			string tournamentName = m_Socket.ReadString();
			int key = m_Socket.ReadInt32();
			lock (m_ActionKeys)
			{
				m_ActionKeys.Remove(tournamentName);
				m_ActionKeys.Add(tournamentName, key);
			}
			int timeOut = m_Socket.ReadInt32();
			OnTournamentRebuy(tournamentName, timeOut);
		}

		protected void OnKeepAlive()
		{
			lock (m_Socket)
			{
				m_Socket.KeepAlive();
			}
		}

		protected void OnAskBuyIn()
		{
			string tableName = m_Socket.ReadString();
			int seatIndex = m_Socket.ReadByte();
			ulong bankroll = m_Socket.ReadUInt64();
			ulong minBuyIn = m_Socket.ReadUInt64();
			ulong maxBuyIn = m_Socket.ReadUInt64();
			OnAskBuyIn(tableName, seatIndex, bankroll, minBuyIn, maxBuyIn);
		}

		public abstract void OnLobby(List<PokerTableInfo> cashGames, List<PokerTournamentInfo> tournaments);
		public abstract void OnInitTable(PokerTableView view);
		public abstract void OnClientConnected();
		public abstract void OnClientLogin(string login);
		public abstract void OnClientLoginFail(string login, string reason);
		public abstract void OnClosedCards(string tableName, CardList cards);
		public abstract void OnShowCards(string tableName, CardList cards);
		public abstract void OnClientMessage(string message);
		public abstract void OnServerMessage(string message);
		public abstract void OnAction(string tableName, ulong call, ulong raise, ulong allin, int timeOut);
		public abstract void OnActionShow(string tableName, int timeOut);
		public abstract void OnActionPost(string tableName, bool smallAndBig, int timeOut);
		public abstract void OnTableImage(string playerName, Image image);
		public abstract void OnTimer(string tableName, int seatIndex, int timeOut);
		public abstract void OnException(Exception e);
		public abstract void OnClientDisconnected();
		public abstract void OnChatMessage(string tableName, string playerName, string message);
		public abstract void OnBankroll(ulong bankroll);
		public abstract void OnActionDone(string tableName, string playerName, PokerActionType action, ulong amount);
		public abstract void OnTournamentFinished(string tournamentName, int position, ulong amount, PokerCurrency currency);
		public abstract void OnBlindGoesUp(string tableName, ulong smallBlind, ulong bigBlind, ulong ante);
		public abstract void OnTournamentLobby(string tournamentName, bool isRegistred);
		public abstract void OnTournamentRegister(string tournamentName);
		public abstract void OnTournamentUnregister(string tournamentName);
		public abstract void OnTournamentLobbyPlayers(string tournamentName, List<KeyValuePair<string, ulong>> players);
		public abstract void OnTournamentLobbyBettingStructure(string tournamentName, List<PokerTournamentConfiguration.BettingStructureEntry> bettingStructure);
		public abstract void OnTournamentLobbyPayoutStructure(string tournamentName, List<PokerTournamentConfiguration.PayoutEntry> payoutStructure);
		public abstract void OnAskBuyIn(string tableName, int seatIndex, ulong bankrol, ulong minBuyIn, ulong maxBuyIn);
		public abstract void OnTournamentRebuy(string tournamentName, int timeOut);
	}
}
